package lynch.net
{
	import Elegant.utils.core.Singleton;
	import flash.events.Event;
	import flash.events.EventDispatcher;
	import flash.events.IOErrorEvent;
	import flash.events.ProgressEvent;
	import flash.events.SecurityErrorEvent;
	import flash.net.ObjectEncoding;
	import flash.net.Socket;
	import flash.system.Security;
	import flash.utils.ByteArray;
	
	/**
	 * send and receive with amf
	 * @author 小痛
	 */
	public class SocketConnector extends EventDispatcher
	{
		/**
		 * called when some msgs come
		 */
		public var receiveder:Function;
		private var _socket:Socket;
		
		public function SocketConnector()
		{
			_socket = new Socket();
			_socket.objectEncoding = ObjectEncoding.AMF3;
			_socket.addEventListener(Event.CONNECT, handler);
			_socket.addEventListener(Event.CLOSE, handler);
			_socket.addEventListener(IOErrorEvent.IO_ERROR, handler);
			_socket.addEventListener(SecurityErrorEvent.SECURITY_ERROR, handler);
			_socket.addEventListener(ProgressEvent.SOCKET_DATA, received);
		}
		
		/** @private **/
		arcane static function initialize():SocketConnector
		{
			return Singleton.create(SocketConnector);
		}
		
		/**
		 * connect to host:port
		 * @param	host
		 * @param	port
		 */
		public function connect(host:String, port:int):void
		{
			Security.loadPolicyFile("xmlsocket://" + host + ":" + port);
			_socket.connect(host, port);
		}
		
		/** close the connection with server **/
		public function close():void
		{
			this._socket.close();
		}
		
		/**
		 * send compressed byteArray to server
		 * @param	params
		 */
		public function send(params:Object):void
		{
			var bytes:ByteArray = new ByteArray();
			bytes.writeObject(params);
			bytes.compress();
			
			_socket.writeBytes(bytes);
			_socket.flush();
		}
		
		private function received(e:ProgressEvent):void
		{
			var bytes:ByteArray = new ByteArray();
			while (_socket.bytesAvailable > 0)
			{
				_socket.readBytes(bytes, 0, _socket.bytesAvailable);
			}
			
			bytes.uncompress();
			
			//called the protocol in Server
			receiveder(bytes.readObject());
			bytes.clear();
		}
		
		private function handler(e:Event):void
		{
			//for handle part in future
			switch (e.type)
			{
				case Event.CLOSE: 
				case IOErrorEvent.IO_ERROR: 
				case SecurityErrorEvent.SECURITY_ERROR: 
					trace("Socket connect error: " + e.type);
				case Event.CONNECT:
				default:
					dispatchEvent(e);
			}
		}
	}
}